CommandAgent whitespace+Open3 fix

ZirconCode 11 years ago
parent
commit
03f60e71af
2 changed files with 79 additions and 66 deletions
  1. 23 10
      app/models/agents/command_agent.rb
  2. 56 56
      spec/models/agents/command_agent_spec.rb

+ 23 - 10
app/models/agents/command_agent.rb

@@ -1,11 +1,14 @@
1 1
 module Agents
2 2
   class CommandAgent < Agent
3 3
     
4
+    require 'open3'
5
+
4 6
 
5 7
     default_schedule "midnight"
6 8
 
7 9
 
8 10
     description <<-MD
11
+
9 12
       The CommandAgent can execute commands on your local system, returning the output.
10 13
 
11 14
       `command` specifies the command to be executed, and `path` will tell CommandAgent in what directory to run this command.
@@ -14,7 +17,9 @@ module Agents
14 17
 
15 18
       CommandAgent can also act upon recieveing events. These events may contain their own path and command arguments. If they do not, CommandAgent will use the configured options. For this reason, please specify defaults even if you are planning to have this Agent respond to events.
16 19
 
17
-      The resulting event will contain the `command` which was executed, the `path` it was executed under, the `exit_status` of the command, and the actual `output`. CommandAgent will not log an error if the `exit_status` implies that something went wrong.
20
+      The resulting event will contain the `command` which was executed, the `path` it was executed under, the `exit_status` of the command, the `errors`, and the actual `output`. CommandAgent will not log an error if the result implies that something went wrong.
21
+
22
+      *Warning*: Misuse of this Agent can pose a security threat.
18 23
 
19 24
     MD
20 25
 
@@ -25,7 +30,8 @@ module Agents
25 30
         'command' => 'pwd',
26 31
         'path' => '/home/Huginn',
27 32
         'exit_status' => '0',
28
-        'output' => '/home' 
33
+        'errors' => '',
34
+        'output' => '/home/Huginn' 
29 35
       }
30 36
     MD
31 37
 
@@ -55,18 +61,25 @@ module Agents
55 61
       path = opts['path'] || options['path']
56 62
 
57 63
       result = nil
58
-      proc_stat = nil
64
+      errors = nil
65
+      exit_status = nil
66
+
59 67
       Dir.chdir(path){
60
-        result = `#{command}`
61
-        proc_stat = $?
68
+        begin
69
+          stdin, stdout, stderr, wait_thr = Open3.popen3(command)
70
+          exit_status = wait_thr.value.to_i
71
+          result = stdout.gets(nil)
72
+          errors = stderr.gets(nil)
73
+        rescue Exception => e
74
+          errors = e.to_s
75
+        end
62 76
       }
63 77
 
64
-      exit_status = -404 # should never happen, but $? is global
65
-      exit_status = proc_stat.to_i if(proc_stat.is_a?(Process::Status))
66
-
67
-      result.chomp! if !result.nil?
78
+      result.chomp! if result.is_a?(String)
79
+      result = '' if result.nil?
80
+      errors = '' if errors.nil?
68 81
 
69
-      vals = {"command" => command, "path" => path, "exit_status" => exit_status, "output" => result}
82
+      vals = {"command" => command, "path" => path, "exit_status" => exit_status, "errors" => errors, "output" => result}
70 83
       evnt = create_event :payload => vals
71 84
 
72 85
       log("Ran '#{command}' under '#{path}'", :outbound_event => evnt)

+ 56 - 56
spec/models/agents/command_agent_spec.rb

@@ -2,69 +2,69 @@ require 'spec_helper'
2 2
 
3 3
 describe Agents::CommandAgent do
4 4
 
5
-	before do
6
-		@valid_path = Dir.pwd
7
-		@valid_params = {
8
-							:path 							=> @valid_path,
9
-							:command						=> "pwd",
10
-							:expected_update_period_in_days => "1",
11
-						}
5
+  before do
6
+    @valid_path = Dir.pwd
7
+    @valid_params = {
8
+        :path  => @valid_path,
9
+        :command  => "pwd",
10
+        :expected_update_period_in_days => "1",
11
+      }
12 12
 
13
-		@checker = Agents::CommandAgent.new(:name => "somename", :options => @valid_params)
14
-		@checker.user = users(:jane)
15
-		@checker.save!
13
+    @checker = Agents::CommandAgent.new(:name => "somename", :options => @valid_params)
14
+    @checker.user = users(:jane)
15
+    @checker.save!
16 16
 
17
-		@event = Event.new
18
-        @event.agent = agents(:jane_weather_agent)
19
-        @event.payload = {
20
-            :command => "pwd"
21
-        }
22
-        @event.save!
23
-	end
17
+    @event = Event.new
18
+    @event.agent = agents(:jane_weather_agent)
19
+    @event.payload = {
20
+      :command => "pwd"
21
+    }
22
+    @event.save!
23
+  end
24 24
 
25
-	describe "validation" do
26
-	    before do
27
-	        @checker.should be_valid
28
-	    end
25
+  describe "validation" do
26
+    before do
27
+      @checker.should be_valid
28
+    end
29 29
 
30
-	    it "should validate presence of necessary fields" do
31
-	        @checker.options[:command] = nil
32
-	        @checker.should_not be_valid
33
-	    end
30
+    it "should validate presence of necessary fields" do
31
+      @checker.options[:command] = nil
32
+      @checker.should_not be_valid
33
+    end
34 34
 
35
-	    it "should validate path" do
36
-	        @checker.options[:path] = 'notarealpath/itreallyisnt'
37
-	        @checker.should_not be_valid
38
-	    end
39
-	end
35
+    it "should validate path" do
36
+      @checker.options[:path] = 'notarealpath/itreallyisnt'
37
+      @checker.should_not be_valid
38
+    end
39
+  end
40 40
 
41
-	describe "#working?" do
42
-		it "checks if its generating events as scheduled" do
43
-			@checker.should_not be_working
44
-			@checker.check
45
-			@checker.reload.should be_working
46
-			three_days_from_now = 3.days.from_now
47
-			stub(Time).now { three_days_from_now }
48
-			@checker.should_not be_working
49
-		end
50
-	end
41
+  describe "#working?" do
42
+    it "checks if its generating events as scheduled" do
43
+      @checker.should_not be_working
44
+      @checker.check
45
+      @checker.reload.should be_working
46
+      three_days_from_now = 3.days.from_now
47
+      stub(Time).now { three_days_from_now }
48
+      @checker.should_not be_working
49
+    end
50
+  end
51 51
 
52
-	describe "#check" do
53
-		it "should check that initial run creates an event" do
54
-			expect { @checker.check }.to change { Event.count }.by(1)
55
-		end
56
-	end
52
+  describe "#check" do
53
+    it "should check that initial run creates an event" do
54
+      expect { @checker.check }.to change { Event.count }.by(1)
55
+    end
56
+  end
57 57
 
58
-	describe "#receive" do
59
-	    it "checks if creates events" do
60
-	        @checker.receive([@event])
61
-	        Event.last.payload[:path].should == @valid_path
62
-	    end
63
-	    it "checks if options are taken from event" do
64
-	    	@event.payload[:command] = 'notarealcommand'
65
-	        @checker.receive([@event])
66
-	        Event.last.payload[:command].should == 'notarealcommand'
67
-	    end
68
-	end
58
+  describe "#receive" do
59
+    it "checks if creates events" do
60
+      @checker.receive([@event])
61
+      Event.last.payload[:path].should == @valid_path
62
+    end
63
+    it "checks if options are taken from event" do
64
+      @event.payload[:command] = 'notarealcommand'
65
+      @checker.receive([@event])
66
+      Event.last.payload[:command].should == 'notarealcommand'
67
+    end
68
+  end
69 69
 
70 70
 end